/**
 * User: Oleksii Savchenko
 * Date: 11.02.13
 * Time: 13:23
 */
/**
 * zdom - facade on top of W3C DOM API
 */

/**
 * Factory for znode objects
 * @param {String} selectorOrMarkup
 * @param {Object} attributes
 * @returns {ZNode} ZNode object
 */

zdom = (function () {
    /**
     * Create ZNode object,
     * all methods of znode object should be chainable
     * @param {String} selectorOrMarkup
     * @param {Object} attributes
     * @constructor
     */
    var ZNode = function (selectorOrMarkup, attributes) {
       this.self = this;
        this.self._selectedElement = null;

        if(selectorOrMarkup.tagName) {
            this.self._selectedElement = selectorOrMarkup;
        } else if(!attributes && selectorOrMarkup){
            this.self._selectedElement = document.querySelector(selectorOrMarkup);
        }  else {
            var re1='.*?';  // Non-greedy match on filler
            var re2='((?:[a-z][a-z0-9_]*))';    // Variable Name 1
            var domElement = document.createElement(selectorOrMarkup.match(re1+re2)[1]),
                innerText = document.createTextNode(selectorOrMarkup.substring(selectorOrMarkup.indexOf(">") + 1,
                    selectorOrMarkup.lastIndexOf("<")));
            domElement.appendChild(innerText);
            for(var prop in attributes){
                domElement.setAttribute(prop, attributes[prop]);
            }
            this.self._selectedElement = domElement;
        }

    };

    /**
     * Set attribute for dom node
     * @param {String} name
     * @param {String} value
     * @returns {ZNode}
     */

    ZNode.prototype.attr = function (name, value) {
        var self = this.self;
        if(name && value){
            self._selectedElement.setAttribute(name,value);
            return self;
        } else if(name){
            return self._selectedElement.getAttribute(name);
        } else {
            throw new Error('Function call without arguments');
        }
    };

    /**
     * Set attribute for dom node
     * @param {String} name
     * @returns {ZNode}
     */

    ZNode.prototype.removeAttr = function (name) {
        var self = this.self;
        if(name){
            self._selectedElement.removeAttribute(name);
            return self;
        } else {
            throw new Error('Function call without arguments');
        }
    };


    /**
     * Hide given element  from UI
     * @param {Number} delay - in milliseconds, 0 by default
     */

    ZNode.prototype.hide = function (delay) {
        var self = this.self;
        var delay = delay || 0;
        setTimeout(function(){
            self._selectedElement.setAttribute("style", "display: none");
        }, delay);
        return self;
    };


    /**
     * Show given element on UI
     * @param {Number} delay - in milliseconds, 0 by default
     */

    ZNode.prototype.show = function (delay) {
        var self = this.self;
        var delay = delay || 0;
        setTimeout(function(){
            self._selectedElement.setAttribute("style", "display: block");
        }, delay);
        return self;
    };

    /**
     * Can made visibility of element
     * @param action
     * @param delay
     * @return {*}
     */
    ZNode.prototype.visible = function(action, delay) {
        var self = this.self,
            delay = delay || 0;

        if(action) {
            setTimeout(function(){
                self._selectedElement.setAttribute("style", "visibility: visible");
            }, delay);
            return self;
        } else {
            setTimeout(function(){
                self._selectedElement.setAttribute("style", "visibility: hidden");
            }, delay);
            return self;
        }
    }

    /**
     * Append ZNode to Document
     * @param {String} selector (optional)
     * @return {ZNode}
     */
    ZNode.prototype.appendTo = function (selector) {
        var self = this.self;
        if(selector){
            var node = document.querySelector(selector);
            node.appendChild(self._selectedElement);
        } else {
            throw new Error();
        }
    };

    /**
     * Set and Get element html
     * @param {String} html (optional)
     * @return {ZNode}
     */
    ZNode.prototype.html = function (html) {
        var self = this.self;
        if(html){
            self._selectedElement.innerHTML = html;
            return self;
        } else {
         return  self._selectedElement.innerHTML;
        }
    };

    /**
     * Set form data Array
     * @return {Object}
     */
    ZNode.prototype.serializeArray = function() {
        var self = this.self,
            dataArray = {},
            fieldName,
            fieldVal;
        for (var i = 0; i < self._selectedElement.length; i++) {
            fieldName = self._selectedElement.elements[i].name;
            fieldVal = self._selectedElement.elements[i].value;
            if(fieldVal === undefined || fieldVal === '') continue;
            dataArray[fieldName] = fieldVal;
        }
        return dataArray;
    };

    /**
     * Can set and Get value of form element
     * @param value
     * @return {*}
     */
    ZNode.prototype.val = function(value) {
        var self = this.self;
        if(!value) {
            return self._selectedElement.value;
        } else {
            self._selectedElement.value = value;
            return self;
        }
    };

    /**
     * Create ZNode objects,
     * @param {String} selectorOrMarkup
     * @param {Object} attributes
     */

    var factory = function (selectorOrMarkup, attributes) {
        return new ZNode(selectorOrMarkup, attributes);
    };

    factory.ZNode = ZNode;

    return factory

})();